import os
import cv2
import sys
import shutil
from tkinter import *
import tkinter.filedialog as fd
from tkinter import messagebox
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import time

def getImageAndLabels(path):
    facesSamples=[]
    ids=[]
    i = 0
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    #检测人脸
    face_detector = cv2.CascadeClassifier('D:/haarcascade_frontalface_default.xml')
    #遍历列表中的图片
    i=1
    for imagePath in imagePaths:
        #打开图片
        PIL_img=Image.open(imagePath).convert('L')
        #将图像转换为数组
        img_numpy=np.array(PIL_img,'uint8')
        faces = face_detector.detectMultiScale(img_numpy)
        #获取每张图片的id
        id=i #nt(os.path.split(imagePath)[1].split('.')[0])
        for x,y,w,h in faces:
            facesSamples.append(img_numpy[y:y+h,x:x+w])
            ids.append(id)
    return facesSamples,ids

folder_path='D:/sxtimg'#这里放一张照片
facesSamples, ids = getImageAndLabels(folder_path)
# 获取训练对象
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.train(facesSamples, np.array(ids))
recognizer.write('D:/sxtdata/trainer.yml')#找个文件夹放一下.yml文件

# 人脸识别与绘制矩形框
def facedetect(image):
    dector=cv2.CascadeClassifier('D:/haarcascade_frontalface_alt.xml')
    rects=dector.detectMultiScale(image, scaleFactor=1.1, minNeighbors=20, minSize=(10,10), flags=cv2.CASCADE_SCALE_IMAGE)
    for (x,y,w,h) in rects:
        cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
    return image

# 调用摄像头进行人脸识别
def videoRecognition(count=10):
    cap=cv2.VideoCapture(0,cv2.CAP_DSHOW)
    while True:
        while not cap.isOpened(): # 处理摄像头未正常读取的情况
            time.sleep(1) # 延时1s后再次尝试
            cap.open()
            count=count-1
            if count<=0:
                return False
        ret,frame=cap.read()
        image=facedetect(frame)
        cv2.imshow('Please verify your identity first',image)#请先进行身份验证
        k = cv2.waitKey(1) & 0xFF
        num = 1
        if k == ord('s'):#按下按键s，从视频中截一张图
            cv2.imwrite("D:/sxt/" + str(num) + ".jpg", frame)#从视频中截图，放到一个设置好的文件夹里
            print("sucess to save" + str(num) + ".jpg")
            print("------")
            num += 1
        elif k == ord(' '):#截图后按空格退出摄像头
            break
    cap.release
    cv2.destroyAllWindows()
    return True

def start():
    #path2='D:/trainer'
    videoRecognition()
    path2='D:/sxt'#刚刚截图的文件夹
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    recognizer.read('D:/sxtdata/trainer.yml')#和之前的改成一致
    imagePaths = [os.path.join(path2, f) for f in os.listdir(path2)]
    for imagePath in imagePaths:
        img = cv2.imread(imagePath)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        face_detector = cv2.CascadeClassifier('D:/haarcascade_frontalface_default.xml')
        faces = face_detector.detectMultiScale(gray)
        for x, y, w, h in faces:
            # 人脸识别
            tid, confidence = recognizer.predict(gray[y:y + h, x:x + w])
        print(imagePath,tid,confidence)
        if confidence < 110:
            messagebox.showinfo('提示',f'confidence:{confidence}\n小于110，验证成功')
        else:
            messagebox.showinfo('警告', '验证失败，程序即将退出')
            sys.exit(0)
start()







